{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a5c6de69",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C:\\\\Users\\\\oscar'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%pwd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "99a6c79e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C:\\\\Users\\\\oscar'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "os.getcwd()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "a05b96ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "os.chdir('C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\FOUR_CARNIVORES')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "68fe6dbd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\FOUR_CARNIVORES'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%pwd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "dd13d7f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "from tensorflow import keras\n",
    "#keras.__version__\n",
    "import os, shutil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "fffd2e73",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C:\\Users\\oscar\\Documents\\MOMOCS\\FOUR_CARNIVORES\\cropped2\n",
      "C:\\Users\\oscar\\Documents\\MOMOCS\\FOUR_CARNIVORES\\cropped2\\conv\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "#create a folder named \"conv2\" in directory\n",
    "original_dir = os.path.abspath('C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\FOUR_CARNIVORES\\\\cropped2')\n",
    "# The directory where we will\n",
    "# store our smaller dataset\n",
    "base_dir = os.path.join(original_dir, \"conv\")\n",
    "print(original_dir)\n",
    "print(base_dir)\n",
    "# added by reviewer\n",
    "isdir = os.path.isdir(base_dir) \n",
    "print(isdir) \n",
    "\n",
    "if isdir ==True:\n",
    "    shutil.rmtree(base_dir)\n",
    "\n",
    "os.mkdir(base_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "97901924",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Directories for our training,\n",
    "# validation and test splits\n",
    "train_dir = os.path.join(base_dir, 'train')\n",
    "os.mkdir(train_dir)\n",
    "validation_dir = os.path.join(base_dir, 'validation')\n",
    "os.mkdir(validation_dir)\n",
    "\n",
    "# Directory with our training crocodile pictures\n",
    "train_croc_dir = os.path.join(train_dir, 'CFP')\n",
    "os.mkdir(train_croc_dir)\n",
    "\n",
    "# Directory with our training hyena pictures\n",
    "train_hyena_dir = os.path.join(train_dir, 'HESP')\n",
    "os.mkdir(train_hyena_dir)\n",
    "\n",
    "# Directory with our training leopard pictures\n",
    "train_leop_dir = os.path.join(train_dir, 'LPZP')\n",
    "os.mkdir(train_leop_dir)\n",
    "\n",
    "# Directory with our training lion pictures\n",
    "train_lion_dir = os.path.join(train_dir, 'LZP')\n",
    "os.mkdir(train_lion_dir)\n",
    "\n",
    "\n",
    "# Directory with our validation hyena pictures\n",
    "validation_croc_dir = os.path.join(validation_dir, 'CFP')\n",
    "os.mkdir(validation_croc_dir)\n",
    "\n",
    "# Directory with our validation hyena pictures\n",
    "validation_hyena_dir = os.path.join(validation_dir, 'HESP')\n",
    "os.mkdir(validation_hyena_dir)\n",
    "\n",
    "# Directory with our validation leopard pictures\n",
    "validation_leop_dir = os.path.join(validation_dir, 'LPZP')\n",
    "os.mkdir(validation_leop_dir)\n",
    "\n",
    "# Directory with our validation lion pictures\n",
    "validation_lion_dir = os.path.join(validation_dir, 'LZP')\n",
    "os.mkdir(validation_lion_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "a5a5bf64",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "61\n",
      "['CFP.56.bmp', 'CFP.47.bmp', 'CFP.40.bmp', 'CFP.3.bmp', 'CFP.38.bmp', 'CFP.14.bmp', 'CFP.72.bmp', 'CFP.22.bmp', 'CFP.57.bmp', 'CFP.32.bmp', 'CFP.80.bmp', 'CFP.44.bmp', 'CFP.25.bmp', 'CFP.51.bmp', 'CFP.6.bmp', 'CFP.70.bmp', 'CFP.74.bmp', 'CFP.65.bmp', 'CFP.71.bmp', 'CFP.36.bmp', 'CFP.21.bmp', 'CFP.81.bmp', 'CFP.69.bmp', 'CFP.13.bmp', 'CFP.7.bmp', 'CFP.68.bmp', 'CFP.79.bmp', 'CFP.33.bmp', 'CFP.10.bmp', 'CFP.82.bmp', 'CFP.77.bmp', 'CFP.75.bmp', 'CFP.30.bmp', 'CFP.27.bmp', 'CFP.64.bmp', 'CFP.76.bmp', 'CFP.84.bmp', 'CFP.63.bmp', 'CFP.34.bmp', 'CFP.55.bmp', 'CFP.12.bmp', 'CFP.83.bmp', 'CFP.50.bmp', 'CFP.0.bmp', 'CFP.37.bmp', 'CFP.2.bmp', 'CFP.24.bmp', 'CFP.39.bmp', 'CFP.28.bmp', 'CFP.15.bmp', 'CFP.49.bmp', 'CFP.58.bmp', 'CFP.8.bmp', 'CFP.23.bmp', 'CFP.42.bmp', 'CFP.19.bmp', 'CFP.60.bmp', 'CFP.11.bmp', 'CFP.29.bmp', 'CFP.16.bmp', 'CFP.43.bmp']\n",
      "26\n",
      "['CFP.52.bmp', 'CFP.18.bmp', 'CFP.67.bmp', 'CFP.48.bmp', 'CFP.45.bmp', 'CFP.17.bmp', 'CFP.53.bmp', 'CFP.5.bmp', 'CFP.46.bmp', 'CFP.31.bmp', 'CFP.9.bmp', 'CFP.41.bmp', 'CFP.78.bmp', 'CFP.66.bmp', 'CFP.85.bmp', 'CFP.20.bmp', 'CFP.35.bmp', 'CFP.62.bmp', 'CFP.59.bmp', 'CFP.26.bmp', 'CFP.1.bmp', 'CFP.86.bmp', 'CFP.61.bmp', 'CFP.54.bmp', 'CFP.4.bmp', 'CFP.73.bmp']\n",
      "144\n",
      "['HESP.37.bmp', 'HESP.14.bmp', 'HESP.196.bmp', 'HESP.165.bmp', 'HESP.23.bmp', 'HESP.89.bmp', 'HESP.76.bmp', 'HESP.130.bmp', 'HESP.70.bmp', 'HESP.199.bmp', 'HESP.54.bmp', 'HESP.183.bmp', 'HESP.45.bmp', 'HESP.39.bmp', 'HESP.104.bmp', 'HESP.179.bmp', 'HESP.81.bmp', 'HESP.7.bmp', 'HESP.13.bmp', 'HESP.152.bmp', 'HESP.162.bmp', 'HESP.151.bmp', 'HESP.178.bmp', 'HESP.78.bmp', 'HESP.25.bmp', 'HESP.198.bmp', 'HESP.46.bmp', 'HESP.155.bmp', 'HESP.36.bmp', 'HESP.163.bmp', 'HESP.189.bmp', 'HESP.108.bmp', 'HESP.129.bmp', 'HESP.50.bmp', 'HESP.119.bmp', 'HESP.88.bmp', 'HESP.94.bmp', 'HESP.43.bmp', 'HESP.68.bmp', 'HESP.150.bmp', 'HESP.65.bmp', 'HESP.64.bmp', 'HESP.32.bmp', 'HESP.27.bmp', 'HESP.47.bmp', 'HESP.75.bmp', 'HESP.182.bmp', 'HESP.29.bmp', 'HESP.114.bmp', 'HESP.6.bmp', 'HESP.142.bmp', 'HESP.195.bmp', 'HESP.103.bmp', 'HESP.200.bmp', 'HESP.4.bmp', 'HESP.117.bmp', 'HESP.181.bmp', 'HESP.166.bmp', 'HESP.101.bmp', 'HESP.2.bmp', 'HESP.192.bmp', 'HESP.26.bmp', 'HESP.139.bmp', 'HESP.12.bmp', 'HESP.56.bmp', 'HESP.85.bmp', 'HESP.73.bmp', 'HESP.180.bmp', 'HESP.100.bmp', 'HESP.202.bmp', 'HESP.17.bmp', 'HESP.86.bmp', 'HESP.59.bmp', 'HESP.62.bmp', 'HESP.203.bmp', 'HESP.141.bmp', 'HESP.82.bmp', 'HESP.102.bmp', 'HESP.170.bmp', 'HESP.168.bmp', 'HESP.177.bmp', 'HESP.30.bmp', 'HESP.188.bmp', 'HESP.160.bmp', 'HESP.158.bmp', 'HESP.74.bmp', 'HESP.51.bmp', 'HESP.122.bmp', 'HESP.33.bmp', 'HESP.10.bmp', 'HESP.126.bmp', 'HESP.205.bmp', 'HESP.201.bmp', 'HESP.5.bmp', 'HESP.91.bmp', 'HESP.69.bmp', 'HESP.0.bmp', 'HESP.131.bmp', 'HESP.124.bmp', 'HESP.194.bmp', 'HESP.191.bmp', 'HESP.134.bmp', 'HESP.143.bmp', 'HESP.106.bmp', 'HESP.99.bmp', 'HESP.153.bmp', 'HESP.144.bmp', 'HESP.148.bmp', 'HESP.84.bmp', 'HESP.21.bmp', 'HESP.132.bmp', 'HESP.58.bmp', 'HESP.161.bmp', 'HESP.15.bmp', 'HESP.110.bmp', 'HESP.22.bmp', 'HESP.66.bmp', 'HESP.79.bmp', 'HESP.138.bmp', 'HESP.184.bmp', 'HESP.87.bmp', 'HESP.31.bmp', 'HESP.145.bmp', 'HESP.53.bmp', 'HESP.55.bmp', 'HESP.175.bmp', 'HESP.121.bmp', 'HESP.48.bmp', 'HESP.42.bmp', 'HESP.113.bmp', 'HESP.24.bmp', 'HESP.28.bmp', 'HESP.135.bmp', 'HESP.95.bmp', 'HESP.98.bmp', 'HESP.38.bmp', 'HESP.20.bmp', 'HESP.136.bmp', 'HESP.18.bmp', 'HESP.159.bmp', 'HESP.127.bmp', 'HESP.193.bmp', 'HESP.9.bmp', 'HESP.156.bmp']\n",
      "62\n",
      "['HESP.105.bmp', 'HESP.57.bmp', 'HESP.40.bmp', 'HESP.128.bmp', 'HESP.190.bmp', 'HESP.164.bmp', 'HESP.16.bmp', 'HESP.120.bmp', 'HESP.111.bmp', 'HESP.115.bmp', 'HESP.140.bmp', 'HESP.80.bmp', 'HESP.173.bmp', 'HESP.93.bmp', 'HESP.137.bmp', 'HESP.174.bmp', 'HESP.49.bmp', 'HESP.171.bmp', 'HESP.60.bmp', 'HESP.1.bmp', 'HESP.149.bmp', 'HESP.186.bmp', 'HESP.96.bmp', 'HESP.157.bmp', 'HESP.112.bmp', 'HESP.61.bmp', 'HESP.176.bmp', 'HESP.34.bmp', 'HESP.187.bmp', 'HESP.169.bmp', 'HESP.77.bmp', 'HESP.44.bmp', 'HESP.116.bmp', 'HESP.67.bmp', 'HESP.172.bmp', 'HESP.72.bmp', 'HESP.185.bmp', 'HESP.97.bmp', 'HESP.90.bmp', 'HESP.154.bmp', 'HESP.35.bmp', 'HESP.107.bmp', 'HESP.11.bmp', 'HESP.92.bmp', 'HESP.63.bmp', 'HESP.19.bmp', 'HESP.83.bmp', 'HESP.197.bmp', 'HESP.133.bmp', 'HESP.204.bmp', 'HESP.41.bmp', 'HESP.167.bmp', 'HESP.71.bmp', 'HESP.125.bmp', 'HESP.118.bmp', 'HESP.52.bmp', 'HESP.3.bmp', 'HESP.147.bmp', 'HESP.123.bmp', 'HESP.109.bmp', 'HESP.8.bmp', 'HESP.146.bmp']\n",
      "85\n",
      "['LPZP.39.bmp', 'LPZP.72.bmp', 'LPZP.115.bmp', 'LPZP.29.bmp', 'LPZP.18.bmp', 'LPZP.88.bmp', 'LPZP.117.bmp', 'LPZP.75.bmp', 'LPZP.113.bmp', 'LPZP.109.bmp', 'LPZP.11.bmp', 'LPZP.52.bmp', 'LPZP.27.bmp', 'LPZP.50.bmp', 'LPZP.65.bmp', 'LPZP.49.bmp', 'LPZP.64.bmp', 'LPZP.63.bmp', 'LPZP.44.bmp', 'LPZP.25.bmp', 'LPZP.3.bmp', 'LPZP.43.bmp', 'LPZP.16.bmp', 'LPZP.94.bmp', 'LPZP.93.bmp', 'LPZP.8.bmp', 'LPZP.21.bmp', 'LPZP.112.bmp', 'LPZP.81.bmp', 'LPZP.67.bmp', 'LPZP.13.bmp', 'LPZP.89.bmp', 'LPZP.12.bmp', 'LPZP.79.bmp', 'LPZP.28.bmp', 'LPZP.6.bmp', 'LPZP.7.bmp', 'LPZP.69.bmp', 'LPZP.47.bmp', 'LPZP.23.bmp', 'LPZP.90.bmp', 'LPZP.71.bmp', 'LPZP.101.bmp', 'LPZP.76.bmp', 'LPZP.34.bmp', 'LPZP.107.bmp', 'LPZP.42.bmp', 'LPZP.70.bmp', 'LPZP.19.bmp', 'LPZP.100.bmp', 'LPZP.51.bmp', 'LPZP.2.bmp', 'LPZP.15.bmp', 'LPZP.114.bmp', 'LPZP.14.bmp', 'LPZP.91.bmp', 'LPZP.10.bmp', 'LPZP.32.bmp', 'LPZP.118.bmp', 'LPZP.106.bmp', 'LPZP.37.bmp', 'LPZP.102.bmp', 'LPZP.110.bmp', 'LPZP.60.bmp', 'LPZP.55.bmp', 'LPZP.57.bmp', 'LPZP.40.bmp', 'LPZP.116.bmp', 'LPZP.108.bmp', 'LPZP.68.bmp', 'LPZP.85.bmp', 'LPZP.24.bmp', 'LPZP.82.bmp', 'LPZP.80.bmp', 'LPZP.0.bmp', 'LPZP.74.bmp', 'LPZP.97.bmp', 'LPZP.92.bmp', 'LPZP.78.bmp', 'LPZP.56.bmp', 'LPZP.30.bmp', 'LPZP.87.bmp', 'LPZP.99.bmp', 'LPZP.98.bmp', 'LPZP.84.bmp']\n",
      "36\n",
      "['LPZP.38.bmp', 'LPZP.22.bmp', 'LPZP.58.bmp', 'LPZP.33.bmp', 'LPZP.86.bmp', 'LPZP.36.bmp', 'LPZP.96.bmp', 'LPZP.48.bmp', 'LPZP.45.bmp', 'LPZP.77.bmp', 'LPZP.17.bmp', 'LPZP.53.bmp', 'LPZP.5.bmp', 'LPZP.46.bmp', 'LPZP.95.bmp', 'LPZP.31.bmp', 'LPZP.9.bmp', 'LPZP.41.bmp', 'LPZP.111.bmp', 'LPZP.66.bmp', 'LPZP.119.bmp', 'LPZP.20.bmp', 'LPZP.103.bmp', 'LPZP.83.bmp', 'LPZP.35.bmp', 'LPZP.105.bmp', 'LPZP.62.bmp', 'LPZP.104.bmp', 'LPZP.59.bmp', 'LPZP.26.bmp', 'LPZP.1.bmp', 'LPZP.120.bmp', 'LPZP.61.bmp', 'LPZP.54.bmp', 'LPZP.4.bmp', 'LPZP.73.bmp']\n",
      "92\n",
      "['LZP.18.bmp', 'LZP.51.bmp', 'LZP.106.bmp', 'LZP.37.bmp', 'LZP.43.bmp', 'LZP.72.bmp', 'LZP.44.bmp', 'LZP.2.bmp', 'LZP.47.bmp', 'LZP.112.bmp', 'LZP.92.bmp', 'LZP.16.bmp', 'LZP.127.bmp', 'LZP.25.bmp', 'LZP.14.bmp', 'LZP.32.bmp', 'LZP.1.bmp', 'LZP.61.bmp', 'LZP.85.bmp', 'LZP.75.bmp', 'LZP.13.bmp', 'LZP.122.bmp', 'LZP.121.bmp', 'LZP.39.bmp', 'LZP.125.bmp', 'LZP.119.bmp', 'LZP.116.bmp', 'LZP.71.bmp', 'LZP.69.bmp', 'LZP.21.bmp', 'LZP.101.bmp', 'LZP.115.bmp', 'LZP.29.bmp', 'LZP.50.bmp', 'LZP.88.bmp', 'LZP.11.bmp', 'LZP.100.bmp', 'LZP.49.bmp', 'LZP.120.bmp', 'LZP.15.bmp', 'LZP.79.bmp', 'LZP.126.bmp', 'LZP.27.bmp', 'LZP.98.bmp', 'LZP.12.bmp', 'LZP.10.bmp', 'LZP.80.bmp', 'LZP.6.bmp', 'LZP.7.bmp', 'LZP.90.bmp', 'LZP.73.bmp', 'LZP.23.bmp', 'LZP.102.bmp', 'LZP.82.bmp', 'LZP.113.bmp', 'LZP.97.bmp', 'LZP.54.bmp', 'LZP.34.bmp', 'LZP.76.bmp', 'LZP.42.bmp', 'LZP.81.bmp', 'LZP.67.bmp', 'LZP.19.bmp', 'LZP.63.bmp', 'LZP.65.bmp', 'LZP.117.bmp', 'LZP.89.bmp', 'LZP.52.bmp', 'LZP.28.bmp', 'LZP.118.bmp', 'LZP.64.bmp', 'LZP.114.bmp', 'LZP.130.bmp', 'LZP.60.bmp', 'LZP.55.bmp', 'LZP.57.bmp', 'LZP.70.bmp', 'LZP.40.bmp', 'LZP.111.bmp', 'LZP.94.bmp', 'LZP.68.bmp', 'LZP.96.bmp', 'LZP.24.bmp', 'LZP.93.bmp', 'LZP.91.bmp', 'LZP.0.bmp', 'LZP.74.bmp', 'LZP.129.bmp', 'LZP.124.bmp', 'LZP.78.bmp', 'LZP.56.bmp', 'LZP.30.bmp']\n",
      "39\n",
      "['LZP.99.bmp', 'LZP.107.bmp', 'LZP.110.bmp', 'LZP.84.bmp', 'LZP.38.bmp', 'LZP.87.bmp', 'LZP.22.bmp', 'LZP.58.bmp', 'LZP.33.bmp', 'LZP.86.bmp', 'LZP.36.bmp', 'LZP.108.bmp', 'LZP.48.bmp', 'LZP.45.bmp', 'LZP.77.bmp', 'LZP.17.bmp', 'LZP.53.bmp', 'LZP.5.bmp', 'LZP.46.bmp', 'LZP.95.bmp', 'LZP.31.bmp', 'LZP.9.bmp', 'LZP.41.bmp', 'LZP.128.bmp', 'LZP.66.bmp', 'LZP.4.bmp', 'LZP.20.bmp', 'LZP.103.bmp', 'LZP.83.bmp', 'LZP.35.bmp', 'LZP.105.bmp', 'LZP.62.bmp', 'LZP.104.bmp', 'LZP.59.bmp', 'LZP.26.bmp', 'LZP.3.bmp', 'LZP.123.bmp', 'LZP.109.bmp', 'LZP.8.bmp']\n"
     ]
    }
   ],
   "source": [
    "#USE THIS ONE\n",
    "\n",
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
    "# randomize order of image locations\n",
    "# this will help model in not being data sequence dependent\n",
    "\n",
    "# Copy first CM images to train_lion_dir\n",
    "import random\n",
    "    \n",
    "    \n",
    "# Copy first TM images to train_croc_dir # \n",
    "fnames = ['CFP.{}.bmp'.format(i) for i in range(87)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:61]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_croc_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next TM images to validation_croc_dir\n",
    "fnamesv = fnames[61:87]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_croc_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "    \n",
    "    \n",
    "    \n",
    "# Copy first TM images to train_hyena_dir # \n",
    "fnames = ['HESP.{}.bmp'.format(i) for i in range(206)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:144]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_hyena_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next 10 TM images to validation_hip_dir\n",
    "fnamesv = fnames[144:206]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_hyena_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "    \n",
    "    \n",
    "    \n",
    "# Copy first TM images to train_leop_dir # \n",
    "fnames = ['LPZP.{}.bmp'.format(i) for i in range(121)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:85]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_leop_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next 10 TM images to validation_leop_dir\n",
    "fnamesv = fnames[85:121]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_leop_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "         \n",
    "        \n",
    "\n",
    "\n",
    "# Copy first TM images to train_lion_dir # \n",
    "fnames = ['LZP.{}.bmp'.format(i) for i in range(131)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:92]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_lion_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next 10 TM images to validation_red_dir\n",
    "fnamesv = fnames[92:131]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_lion_dir, fname)\n",
    "    shutil.copyfile(src, dst)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf1b1c84",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#training and testing sets"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3fac3f4",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### Colour agnostic implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8984506e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "2b012e82",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
    "#from tensorflow.keras.applications.resnet50 import preprocess_input\n",
    "from tensorflow.keras.applications.densenet import preprocess_input\n",
    "#from tensorflow.keras.applications.vgg19 import preprocess_input\n",
    "import cv2\n",
    "\n",
    "def random_hue_brightness_saturation(image):\n",
    "    # Convert the image to HSV\n",
    "    hsv_image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)\n",
    "    \n",
    "    # Randomly choose which adjustment to apply\n",
    "    random_value = np.random.randint(0, 3)\n",
    "    \n",
    "    if random_value == 0:\n",
    "        # Randomly adjust hue\n",
    "        hue_shift = np.random.uniform(-10, 10)\n",
    "        hsv_image[:, :, 0] = (hsv_image[:, :, 0] + hue_shift) % 180\n",
    "    elif random_value == 1:\n",
    "        # Randomly adjust saturation\n",
    "        saturation_scale = np.random.uniform(0.8, 1.2)\n",
    "        hsv_image[:, :, 1] = np.clip(hsv_image[:, :, 1] * saturation_scale, 0, 255)\n",
    "    else:\n",
    "        # Randomly adjust brightness\n",
    "        brightness_scale = np.random.uniform(0.8, 1.2)\n",
    "        hsv_image[:, :, 2] = np.clip(hsv_image[:, :, 2] * brightness_scale, 0, 255)\n",
    "    \n",
    "    # Convert back to RGB\n",
    "    augmented_image = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2RGB)\n",
    "    \n",
    "    # Apply ResNet50 preprocessing\n",
    "    augmented_image = preprocess_input(augmented_image)\n",
    "    \n",
    "    return augmented_image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6e2c7e3a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "51baa7a7",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 382 images belonging to 4 classes.\n",
      "Found 163 images belonging to 4 classes.\n"
     ]
    }
   ],
   "source": [
    "#from tensorflow.keras.applications.densenet import preprocess_input #for RESNET 50\n",
    "#from keras.applications.imagenet_utils import decode_predictions, preprocess_input#for efficient Net\n",
    "#from tensorflow.keras.applications.imagenet_utils import decode_predictions, preprocess_input#for efficient Net\n",
    "\n",
    "#Let's train our network using data augmentation and dropout:\n",
    "train_datagen = ImageDataGenerator(\n",
    "    rotation_range=40,\n",
    "    width_shift_range=0.2,\n",
    "    height_shift_range=0.2,\n",
    "    shear_range=0.2,\n",
    "    zoom_range=0.2,\n",
    "    horizontal_flip=True,\n",
    "    preprocessing_function=random_hue_brightness_saturation)#OJO!!!! imagenet_utils for Efficient Net\n",
    "\n",
    "# Note that the validation data should not be augmented!\n",
    "test_datagen = ImageDataGenerator(preprocessing_function= \\\n",
    "    keras.applications.densenet.preprocess_input)#OJO!!!\n",
    "\n",
    "train_generator = train_datagen.flow_from_directory(\n",
    "        # This is the target directory\n",
    "        train_dir,\n",
    "        # All images will be resized \n",
    "        target_size=(250, 200),\n",
    "        batch_size=32,\n",
    "        class_mode='categorical')#put \"categorical\" si son más de 2 categorías\n",
    "\n",
    "validation_generator = test_datagen.flow_from_directory(\n",
    "        validation_dir,\n",
    "        target_size=(250, 200),\n",
    "        batch_size=20,\n",
    "        class_mode='categorical',\n",
    "        shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "ec22b468",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 382 images belonging to 4 classes.\n",
      "Found 163 images belonging to 4 classes.\n",
      "(382, 250, 200, 3) train samples\n",
      "(163, 250, 200, 3) test samples\n"
     ]
    }
   ],
   "source": [
    "datagenTrain=train_datagen.flow_from_directory(\n",
    "        # This is the target directory\n",
    "        train_dir,\n",
    "        # All images will be resized to 40x160\n",
    "        target_size=(250,200),\n",
    "        batch_size=382,\n",
    "        # Since we use binary_crossentropy loss, we need binary labels\n",
    "        class_mode='categorical')\n",
    "datagenTest=test_datagen.flow_from_directory(\n",
    "        # This is the target directory\n",
    "        validation_dir,\n",
    "        # All images will be resized to 40x160\n",
    "        target_size=(250, 200),\n",
    "        batch_size=163,\n",
    "        # Since we use binary_crossentropy loss, we need binary labels\n",
    "        class_mode='categorical',\n",
    "        shuffle=False)\n",
    "x_train, y_train = next(datagenTrain)\n",
    "x_test, y_test = next(datagenTest)\n",
    "print(x_train.shape, 'train samples')\n",
    "print(x_test.shape, 'test samples')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "022ee854",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "995f9b2e",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#MODULE 2: CHOOSE MODEL"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "857e863a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# For adding new activation function\n",
    "from keras.layers import Activation\n",
    "from keras import backend as K\n",
    "from tensorflow.python.keras.utils.generic_utils import get_custom_objects\n",
    "#from keras.utils.generic_utils import get_custom_objects\n",
    "def swish(x):\n",
    "    return (K.sigmoid(x) * x)\n",
    "\n",
    "get_custom_objects().update({'swish': Activation(swish)})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "da6bb8db",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#activate Dropout "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "487ab902",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:`lr` is deprecated in Keras optimizer, please use `learning_rate` or use the legacy optimizer, e.g.,tf.keras.optimizers.legacy.Adagrad.\n"
     ]
    }
   ],
   "source": [
    "# Vgg19 for transfer learning with Dropout\n",
    "import sys\n",
    "\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.vgg19 import VGG19\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "#from keras.optimizers import SGD\n",
    "from keras.optimizers import Adagrad\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = VGG19(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='swish', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\t#opt = SGD(lr=0.001, momentum=0.9)\n",
    "\topt = Adagrad (lr=0.001)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4fd3cd39",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "eb0b0fba",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:`lr` is deprecated in Keras optimizer, please use `learning_rate` or use the legacy optimizer, e.g.,tf.keras.optimizers.legacy.Adagrad.\n"
     ]
    }
   ],
   "source": [
    "# for transfer learning RESNET50 with Dropout\n",
    "#import sys\n",
    "#from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.resnet50 import ResNet50\n",
    "from tensorflow.keras.models import Model\n",
    "from tensorflow.keras.layers import Dense\n",
    "from tensorflow.keras.layers import Flatten\n",
    "from tensorflow.keras.layers import Dropout\n",
    "from tensorflow.keras.optimizers import SGD\n",
    "from tensorflow.keras.optimizers import Adagrad\n",
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = ResNet50(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='swish', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\t#opt = SGD(lr=0.001, momentum=0.9)\n",
    "\topt = Adagrad(lr=0.001)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5ea2e84a",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "3469f2bd",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:`lr` is deprecated in Keras optimizer, please use `learning_rate` or use the legacy optimizer, e.g.,tf.keras.optimizers.legacy.Adagrad.\n"
     ]
    }
   ],
   "source": [
    "# for transfer learning DENSENET with Dropout\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.densenet import DenseNet201\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.optimizers import SGD\n",
    "from keras.optimizers import Adagrad\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = DenseNet201(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile \n",
    "\t#opt = SGD(lr=0.001, momentum=0.9)   \n",
    "\topt = Adagrad(lr=0.001)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "b81fa27c",
   "metadata": {},
   "outputs": [],
   "source": [
    "#RUN MODEL:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "d01755ee",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\oscar\\AppData\\Local\\Temp\\ipykernel_66620\\1142911488.py:2: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators.\n",
      "  history = model.fit_generator(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/100\n",
      "12/12 [==============================] - 129s 9s/step - loss: 2.8106 - accuracy: 0.3665 - val_loss: 1.2895 - val_accuracy: 0.4233\n",
      "Epoch 2/100\n",
      "12/12 [==============================] - 104s 9s/step - loss: 1.1830 - accuracy: 0.4712 - val_loss: 1.0411 - val_accuracy: 0.5583\n",
      "Epoch 3/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 1.1392 - accuracy: 0.4921 - val_loss: 0.9678 - val_accuracy: 0.6074\n",
      "Epoch 4/100\n",
      "12/12 [==============================] - 110s 9s/step - loss: 1.0278 - accuracy: 0.5445 - val_loss: 0.8868 - val_accuracy: 0.6380\n",
      "Epoch 5/100\n",
      "12/12 [==============================] - 104s 9s/step - loss: 1.0095 - accuracy: 0.5550 - val_loss: 0.8749 - val_accuracy: 0.6626\n",
      "Epoch 6/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.8911 - accuracy: 0.6387 - val_loss: 0.8043 - val_accuracy: 0.6503\n",
      "Epoch 7/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.8969 - accuracy: 0.6204 - val_loss: 0.9218 - val_accuracy: 0.5890\n",
      "Epoch 8/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.8674 - accuracy: 0.6466 - val_loss: 0.8147 - val_accuracy: 0.6687\n",
      "Epoch 9/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.8190 - accuracy: 0.6492 - val_loss: 0.7315 - val_accuracy: 0.6994\n",
      "Epoch 10/100\n",
      "12/12 [==============================] - 102s 9s/step - loss: 0.8332 - accuracy: 0.6702 - val_loss: 0.7541 - val_accuracy: 0.6871\n",
      "Epoch 11/100\n",
      "12/12 [==============================] - 109s 9s/step - loss: 0.7917 - accuracy: 0.6466 - val_loss: 0.7151 - val_accuracy: 0.6810\n",
      "Epoch 12/100\n",
      "12/12 [==============================] - 97s 8s/step - loss: 0.7395 - accuracy: 0.6518 - val_loss: 0.7490 - val_accuracy: 0.6871\n",
      "Epoch 13/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.7401 - accuracy: 0.7199 - val_loss: 0.7205 - val_accuracy: 0.7239\n",
      "Epoch 14/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.7222 - accuracy: 0.6963 - val_loss: 0.7445 - val_accuracy: 0.7117\n",
      "Epoch 15/100\n",
      "12/12 [==============================] - 103s 9s/step - loss: 0.7414 - accuracy: 0.6780 - val_loss: 0.6663 - val_accuracy: 0.7117\n",
      "Epoch 16/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.7329 - accuracy: 0.6649 - val_loss: 0.6630 - val_accuracy: 0.7055\n",
      "Epoch 17/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.6969 - accuracy: 0.7147 - val_loss: 0.6961 - val_accuracy: 0.7362\n",
      "Epoch 18/100\n",
      "12/12 [==============================] - 104s 9s/step - loss: 0.6443 - accuracy: 0.7592 - val_loss: 0.6856 - val_accuracy: 0.6871\n",
      "Epoch 19/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.6620 - accuracy: 0.7277 - val_loss: 0.6510 - val_accuracy: 0.7117\n",
      "Epoch 20/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.6636 - accuracy: 0.7173 - val_loss: 0.7212 - val_accuracy: 0.6871\n",
      "Epoch 21/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.6014 - accuracy: 0.7487 - val_loss: 0.6515 - val_accuracy: 0.7423\n",
      "Epoch 22/100\n",
      "12/12 [==============================] - 102s 9s/step - loss: 0.6195 - accuracy: 0.7487 - val_loss: 0.6227 - val_accuracy: 0.7362\n",
      "Epoch 23/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.6145 - accuracy: 0.7618 - val_loss: 0.6535 - val_accuracy: 0.7178\n",
      "Epoch 24/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.6340 - accuracy: 0.7618 - val_loss: 0.6702 - val_accuracy: 0.7055\n",
      "Epoch 25/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.5789 - accuracy: 0.7880 - val_loss: 0.6234 - val_accuracy: 0.7423\n",
      "Epoch 26/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.5872 - accuracy: 0.7618 - val_loss: 0.6526 - val_accuracy: 0.7178\n",
      "Epoch 27/100\n",
      "12/12 [==============================] - 110s 9s/step - loss: 0.5514 - accuracy: 0.7801 - val_loss: 0.6014 - val_accuracy: 0.7362\n",
      "Epoch 28/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.5537 - accuracy: 0.7801 - val_loss: 0.5961 - val_accuracy: 0.7239\n",
      "Epoch 29/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.5569 - accuracy: 0.7906 - val_loss: 0.6072 - val_accuracy: 0.7607\n",
      "Epoch 30/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.5216 - accuracy: 0.8063 - val_loss: 0.5917 - val_accuracy: 0.7485\n",
      "Epoch 31/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.5349 - accuracy: 0.8010 - val_loss: 0.6004 - val_accuracy: 0.7607\n",
      "Epoch 32/100\n",
      "12/12 [==============================] - 104s 9s/step - loss: 0.5118 - accuracy: 0.7932 - val_loss: 0.6064 - val_accuracy: 0.7362\n",
      "Epoch 33/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.4929 - accuracy: 0.8115 - val_loss: 0.5722 - val_accuracy: 0.7730\n",
      "Epoch 34/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.5153 - accuracy: 0.8115 - val_loss: 0.5690 - val_accuracy: 0.7669\n",
      "Epoch 35/100\n",
      "12/12 [==============================] - 104s 9s/step - loss: 0.5036 - accuracy: 0.8141 - val_loss: 0.5792 - val_accuracy: 0.7607\n",
      "Epoch 36/100\n",
      "12/12 [==============================] - 110s 9s/step - loss: 0.5336 - accuracy: 0.8037 - val_loss: 0.5793 - val_accuracy: 0.7546\n",
      "Epoch 37/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.4858 - accuracy: 0.7880 - val_loss: 0.5747 - val_accuracy: 0.7669\n",
      "Epoch 38/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.5238 - accuracy: 0.7827 - val_loss: 0.5746 - val_accuracy: 0.7730\n",
      "Epoch 39/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.4665 - accuracy: 0.8246 - val_loss: 0.5584 - val_accuracy: 0.8037\n",
      "Epoch 40/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.5025 - accuracy: 0.8194 - val_loss: 0.5611 - val_accuracy: 0.7791\n",
      "Epoch 41/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.4819 - accuracy: 0.8141 - val_loss: 0.6017 - val_accuracy: 0.7546\n",
      "Epoch 42/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.5258 - accuracy: 0.7853 - val_loss: 0.5710 - val_accuracy: 0.7669\n",
      "Epoch 43/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.4742 - accuracy: 0.7984 - val_loss: 0.5802 - val_accuracy: 0.7546\n",
      "Epoch 44/100\n",
      "12/12 [==============================] - 109s 9s/step - loss: 0.4567 - accuracy: 0.8141 - val_loss: 0.5609 - val_accuracy: 0.7730\n",
      "Epoch 45/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.4469 - accuracy: 0.8272 - val_loss: 0.5603 - val_accuracy: 0.7730\n",
      "Epoch 46/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.4402 - accuracy: 0.8560 - val_loss: 0.5895 - val_accuracy: 0.7546\n",
      "Epoch 47/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.4757 - accuracy: 0.7853 - val_loss: 0.5804 - val_accuracy: 0.7669\n",
      "Epoch 48/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.4298 - accuracy: 0.8168 - val_loss: 0.5625 - val_accuracy: 0.7669\n",
      "Epoch 49/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.4023 - accuracy: 0.8560 - val_loss: 0.5492 - val_accuracy: 0.7607\n",
      "Epoch 50/100\n",
      "12/12 [==============================] - 111s 9s/step - loss: 0.4540 - accuracy: 0.8168 - val_loss: 0.5554 - val_accuracy: 0.7791\n",
      "Epoch 51/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.4517 - accuracy: 0.8246 - val_loss: 0.5874 - val_accuracy: 0.7485\n",
      "Epoch 52/100\n",
      "12/12 [==============================] - 102s 9s/step - loss: 0.4380 - accuracy: 0.8534 - val_loss: 0.5759 - val_accuracy: 0.7791\n",
      "Epoch 53/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.4137 - accuracy: 0.8560 - val_loss: 0.5567 - val_accuracy: 0.7607\n",
      "Epoch 54/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3881 - accuracy: 0.8508 - val_loss: 0.5789 - val_accuracy: 0.7546\n",
      "Epoch 55/100\n",
      "12/12 [==============================] - 104s 9s/step - loss: 0.4265 - accuracy: 0.8272 - val_loss: 0.5460 - val_accuracy: 0.7730\n",
      "Epoch 56/100\n",
      "12/12 [==============================] - 109s 9s/step - loss: 0.4000 - accuracy: 0.8403 - val_loss: 0.5415 - val_accuracy: 0.7975\n",
      "Epoch 57/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.4125 - accuracy: 0.8482 - val_loss: 0.5422 - val_accuracy: 0.8098\n",
      "Epoch 58/100\n",
      "12/12 [==============================] - 109s 9s/step - loss: 0.4246 - accuracy: 0.8534 - val_loss: 0.5852 - val_accuracy: 0.7607\n",
      "Epoch 59/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.4056 - accuracy: 0.8377 - val_loss: 0.5543 - val_accuracy: 0.7853\n",
      "Epoch 60/100\n",
      "12/12 [==============================] - 111s 9s/step - loss: 0.3794 - accuracy: 0.8665 - val_loss: 0.5371 - val_accuracy: 0.7914\n",
      "Epoch 61/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.3873 - accuracy: 0.8639 - val_loss: 0.5287 - val_accuracy: 0.7730\n",
      "Epoch 62/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.4230 - accuracy: 0.8246 - val_loss: 0.5676 - val_accuracy: 0.7730\n",
      "Epoch 63/100\n",
      "12/12 [==============================] - 103s 9s/step - loss: 0.3893 - accuracy: 0.8586 - val_loss: 0.5232 - val_accuracy: 0.8098\n",
      "Epoch 64/100\n",
      "12/12 [==============================] - 101s 9s/step - loss: 0.3543 - accuracy: 0.8743 - val_loss: 0.5276 - val_accuracy: 0.8098\n",
      "Epoch 65/100\n",
      "12/12 [==============================] - 102s 9s/step - loss: 0.3881 - accuracy: 0.8482 - val_loss: 0.5658 - val_accuracy: 0.7546\n",
      "Epoch 66/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3711 - accuracy: 0.8665 - val_loss: 0.5530 - val_accuracy: 0.8160\n",
      "Epoch 67/100\n",
      "12/12 [==============================] - 110s 9s/step - loss: 0.3776 - accuracy: 0.8691 - val_loss: 0.5625 - val_accuracy: 0.7730\n",
      "Epoch 68/100\n",
      "12/12 [==============================] - 103s 9s/step - loss: 0.3815 - accuracy: 0.8665 - val_loss: 0.5428 - val_accuracy: 0.7730\n",
      "Epoch 69/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3106 - accuracy: 0.8901 - val_loss: 0.5373 - val_accuracy: 0.7791\n",
      "Epoch 70/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.3677 - accuracy: 0.8743 - val_loss: 0.5371 - val_accuracy: 0.8098\n",
      "Epoch 71/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3997 - accuracy: 0.8403 - val_loss: 0.5491 - val_accuracy: 0.7669\n",
      "Epoch 72/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.3870 - accuracy: 0.8560 - val_loss: 0.5320 - val_accuracy: 0.8098\n",
      "Epoch 73/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.3454 - accuracy: 0.8796 - val_loss: 0.5644 - val_accuracy: 0.7791\n",
      "Epoch 74/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.3257 - accuracy: 0.8874 - val_loss: 0.5620 - val_accuracy: 0.7914\n",
      "Epoch 75/100\n",
      "12/12 [==============================] - 101s 9s/step - loss: 0.3528 - accuracy: 0.8691 - val_loss: 0.5472 - val_accuracy: 0.7730\n",
      "Epoch 76/100\n",
      "12/12 [==============================] - 104s 9s/step - loss: 0.3967 - accuracy: 0.8665 - val_loss: 0.5235 - val_accuracy: 0.8221\n",
      "Epoch 77/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.3575 - accuracy: 0.8717 - val_loss: 0.5684 - val_accuracy: 0.7607\n",
      "Epoch 78/100\n",
      "12/12 [==============================] - 103s 9s/step - loss: 0.3471 - accuracy: 0.8691 - val_loss: 0.5605 - val_accuracy: 0.7730\n",
      "Epoch 79/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.3366 - accuracy: 0.8665 - val_loss: 0.5343 - val_accuracy: 0.8098\n",
      "Epoch 80/100\n",
      "12/12 [==============================] - 104s 9s/step - loss: 0.3600 - accuracy: 0.8665 - val_loss: 0.5233 - val_accuracy: 0.8098\n",
      "Epoch 81/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3205 - accuracy: 0.9110 - val_loss: 0.5676 - val_accuracy: 0.7669\n",
      "Epoch 82/100\n",
      "12/12 [==============================] - 101s 8s/step - loss: 0.3581 - accuracy: 0.8586 - val_loss: 0.5341 - val_accuracy: 0.7975\n",
      "Epoch 83/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3572 - accuracy: 0.8691 - val_loss: 0.5560 - val_accuracy: 0.7791\n",
      "Epoch 84/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3359 - accuracy: 0.8927 - val_loss: 0.5241 - val_accuracy: 0.8098\n",
      "Epoch 85/100\n",
      "12/12 [==============================] - 103s 9s/step - loss: 0.3437 - accuracy: 0.8717 - val_loss: 0.5203 - val_accuracy: 0.8098\n",
      "Epoch 86/100\n",
      "12/12 [==============================] - 102s 9s/step - loss: 0.3300 - accuracy: 0.8927 - val_loss: 0.5486 - val_accuracy: 0.7730\n",
      "Epoch 87/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.3251 - accuracy: 0.9031 - val_loss: 0.5952 - val_accuracy: 0.7607\n",
      "Epoch 88/100\n",
      "12/12 [==============================] - 102s 9s/step - loss: 0.3434 - accuracy: 0.8796 - val_loss: 0.5389 - val_accuracy: 0.7914\n",
      "Epoch 89/100\n",
      "12/12 [==============================] - 105s 9s/step - loss: 0.3169 - accuracy: 0.8874 - val_loss: 0.5610 - val_accuracy: 0.7730\n",
      "Epoch 90/100\n",
      "12/12 [==============================] - 109s 9s/step - loss: 0.3066 - accuracy: 0.9005 - val_loss: 0.5445 - val_accuracy: 0.7975\n",
      "Epoch 91/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3047 - accuracy: 0.8848 - val_loss: 0.5300 - val_accuracy: 0.7853\n",
      "Epoch 92/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3230 - accuracy: 0.8796 - val_loss: 0.5782 - val_accuracy: 0.7669\n",
      "Epoch 93/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3537 - accuracy: 0.8796 - val_loss: 0.5612 - val_accuracy: 0.8037\n",
      "Epoch 94/100\n",
      "12/12 [==============================] - 104s 9s/step - loss: 0.3345 - accuracy: 0.8770 - val_loss: 0.5338 - val_accuracy: 0.7914\n",
      "Epoch 95/100\n",
      "12/12 [==============================] - 104s 9s/step - loss: 0.3251 - accuracy: 0.8796 - val_loss: 0.5409 - val_accuracy: 0.7975\n",
      "Epoch 96/100\n",
      "12/12 [==============================] - 108s 9s/step - loss: 0.3160 - accuracy: 0.9058 - val_loss: 0.5147 - val_accuracy: 0.7914\n",
      "Epoch 97/100\n",
      "12/12 [==============================] - 107s 9s/step - loss: 0.3541 - accuracy: 0.8743 - val_loss: 0.5339 - val_accuracy: 0.7914\n",
      "Epoch 98/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.2706 - accuracy: 0.9188 - val_loss: 0.5543 - val_accuracy: 0.7975\n",
      "Epoch 99/100\n",
      "12/12 [==============================] - 109s 9s/step - loss: 0.2868 - accuracy: 0.9031 - val_loss: 0.5460 - val_accuracy: 0.7914\n",
      "Epoch 100/100\n",
      "12/12 [==============================] - 106s 9s/step - loss: 0.3015 - accuracy: 0.8979 - val_loss: 0.5612 - val_accuracy: 0.7853\n"
     ]
    }
   ],
   "source": [
    "# define model\n",
    "history = model.fit_generator(\n",
    "      train_generator,\n",
    "      steps_per_epoch=12,\n",
    "      epochs=100,\n",
    "      validation_data=validation_generator,\n",
    "      validation_steps=9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "48c5e45b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "567311b6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "fd5ba924",
   "metadata": {},
   "outputs": [],
   "source": [
    "#save model\n",
    "model_json=model.to_json()\n",
    "with open(\"vgg19-swish-Adagrad_ColorAugmentation.json\", \"w\") as json_file:\n",
    "    json_file.write(model_json)\n",
    "#serializar los pesos\n",
    "model.save_weights(\"vgg19-swish-Adagrad_ColorAugmentation.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "2801554e",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\oscar\\AppData\\Local\\Temp\\ipykernel_33280\\1979981568.py:1: UserWarning: `Model.predict_generator` is deprecated and will be removed in a future version. Please use `Model.predict`, which supports generators.\n",
      "  predictions=model.predict_generator(validation_generator, steps=len(validation_generator), verbose=1)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9/9 [==============================] - 9s 992ms/step\n"
     ]
    }
   ],
   "source": [
    "predictions=model.predict_generator(validation_generator, steps=len(validation_generator), verbose=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "51d07cc9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "val_preds = np.round(predictions)# from probabilities to 0 or 1\n",
    "val_trues = validation_generator.classes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "fe41598d",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\oscar\\AppData\\Local\\Temp\\ipykernel_33280\\3852048864.py:7: UserWarning: `Model.predict_generator` is deprecated and will be removed in a future version. Please use `Model.predict`, which supports generators.\n",
      "  Y_pred = model.predict_generator(validation_generator, num_of_test_samples // batch_size+1)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Confusion Matrix\n",
      "[[14  7  4  1]\n",
      " [ 2 53  5  2]\n",
      " [ 0  8 28  0]\n",
      " [ 1  8  5 25]]\n"
     ]
    }
   ],
   "source": [
    "#modify:\n",
    "from sklearn.metrics import confusion_matrix\n",
    "from sklearn.metrics import classification_report\n",
    "import numpy as np\n",
    "num_of_test_samples = 163 #number of testing samples\n",
    "batch_size=20 #batch size for the validation set\n",
    "Y_pred = model.predict_generator(validation_generator, num_of_test_samples // batch_size+1)\n",
    "y_pred = np.argmax(Y_pred, axis=1)\n",
    "print('Confusion Matrix')\n",
    "print(confusion_matrix(validation_generator.classes, y_pred))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "2395fdea",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Classification Report\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "        croc       0.82      0.54      0.65        26\n",
      "       hyena       0.70      0.85      0.77        62\n",
      "     leopard       0.67      0.78      0.72        36\n",
      "        lion       0.89      0.64      0.75        39\n",
      "\n",
      "    accuracy                           0.74       163\n",
      "   macro avg       0.77      0.70      0.72       163\n",
      "weighted avg       0.76      0.74      0.73       163\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print('Classification Report')\n",
    "target_names = [ \"croc\",'hyena', 'leopard', 'lion']\n",
    "print(classification_report(validation_generator.classes, y_pred, target_names=target_names))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3e65c4e",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "18c1a03a",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1ee2112b",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "217fc548",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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DTdg/PjxEEKgYsWK+Oabb5CcnGyzzyZNmgAA3nnnHQwePBjBwcGoV6+eRV8PxaBBgzBnzhwMHjwYJ06cQJMmTfDTTz/htddeQ7du3SxGfXiiR48eSEpKwqhRo9C7d2+cOnUKr7zyCmJjY3H06FHTeu3atcPAgQMxffp0/PXXX+jRowdCQ0Oxd+9eRERE4KmnnkLNmjXx4osv4pVXXsG1a9fQt29fREVF4eDBg8jMzMTUqVMBAAMHDsSAAQMwatQoPPDAAzh58iTefPNNU82K3nLr+Z727dsXixYtwsiRI3HkyBF06tQJBQUF2LFjBxo0aICHH37YtG7dunVx9913Y926dbjtttts+gtRKeDf/rNUmtkbTdOoUSPN9bdt2ybatGkjIiIiRJUqVcTw4cPFnj17bEaq2BtN0717d5t92htFYD2axrqc9o6Tnp4uevXqJcqWLSsiIyPFAw88IL777jub0R1acnJyxHPPPSeqV68uwsLCRIsWLcSqVatsRqAoo2neeustm30AEJMnT7ZY9tFHH4k6deqIkJAQUbduXbFw4ULNUS2O9OvXTwAQt956q+br33zzjWjatKkICwsT1atXF88//7xYt26d5rl0NppGCCEOHjwo7rzzThEWFiYqVqwohg0bJlavXm2zP2W9yMhIUaFCBfHggw+K9PR0zfMwYcIEUa1aNREQEGCxH+vvgBBCXLx4UYwcOVLExsaKoKAgkZCQICZMmCCuX79usR4A8cQTT9icD3ujVqy9/vrrombNmiI0NFQ0aNBAfPjhh5rfK6PRKN5++23RuHFjERISIqKiokSbNm3EN998Y7Hep59+Km666SYRFhYmypYtK5o3b27xt1FQUCDefPNNUatWLREWFiZatWolNm7caPfv4KuvvrIps97vqRByxNrLL79s+v5VqlRJ3H777WLbtm02+128eLEAIL788kun541KHoMQVtlmiMirXnvtNUyaNAnp6ele72BIVFI88MAD+OWXX3DixAkEBwf7uzhUyNhMQ+RF77//PgDZhJCXl4eNGzfi3XffxYABAxiIEFnJycnBnj17sHPnTnz99deYNWsWA5FSisEIkRdFRETg7bffxokTJ5CTk4MaNWrghRdewKRJk/xdNKIiJyMjA23btkW5cuXw2GOP4amnnvJ3kchP2ExDREREfsWhvURERORXDEaIiIjIrxiMEBERkV8Viw6sBQUFOHv2LCIjIzlxEhERUTEhhMDly5edzlNULIKRs2fPOpxvgYiIiIquU6dOOUxvUCyCESVl86lTp1CuXDk/l4aIiIj0yM7ORnx8vObUC+aKRTCiNM2UK1eOwQgREVEx46yLBTuwEhERkV8xGCEiIiK/YjBCREREflUs+ozoIYRAfn4+jEajv4tCxVBgYCCCgoI4dJyIyA9KRDCSm5uLjIwMXL161d9FoWIsIiICsbGxCAkJ8XdRiIhKlWIfjBQUFCAtLQ2BgYGoVq0aQkJC+OuWXCKEQG5uLi5cuIC0tDTUqVPHYXIeIiLyrmIfjOTm5qKgoADx8fGIiIjwd3GomAoPD0dwcDBOnjyJ3NxchIWF+btIRESlRon5+cdfsuQpfoeIiPyj2NeMEBERkS2jEUhJATIygNhYoF07IDDQ36XSxmCEiIiohElKAkaPBk6fVpfFxQHvvAP06uW/ctnDeun/GI3A5s3AF1/I++I4Qrhjx44YM2aM7vVPnDgBg8GA1NRUn5WJiIgKV1IS0Lu3ZSACAGfOyOVJSf4plyOsGUHhR5DORvsMHjwYixcvdnm/SUlJCA4O1r1+fHw8MjIyULlyZZePRURERY/RKK9nQti+JgRgMABjxgA9exatJptSH4woEaT1B6dEkCtWeD8gycjIMD1etmwZXn75ZRw5csS0LDw83GL9vLw8XUFGxYoVXSpHYGAgYmJiXNqGiIiKrpQU2xoRc0IAp07J9Tp2LLRiOVWqm2mcRZCAjCC93WQTExNjukVFRcFgMJieX79+HeXLl8fy5cvRsWNHhIWFYcmSJbh48SL69u2LuLg4REREoEmTJvjiiy8s9mvdTFOzZk289tprGDp0KCIjI1GjRg0sWLDA9Lp1M83mzZthMBiwYcMGtGrVChEREWjbtq1FoAQA06dPR9WqVREZGYnhw4dj/PjxaNasmd33azQaMWzYMCQmJiI8PBz16tXDO++8Y7PewoUL0ahRI4SGhiI2NhZPPvmk6bV//vkHjz76KKKjoxEWFobGjRtj7dq1Lpx1IirOSkJTemEw+63rlfUKS6kORlyJIAvbCy+8gKeffhqHDh3CXXfdhevXr6Nly5ZYu3YtDhw4gEcffRQDBw7Ejh07HO5n5syZaNWqFfbu3YtRo0bh8ccfx+HDhx1uM3HiRMycORO//vorgoKCMHToUNNrS5cuxauvvoo33ngDu3fvRo0aNTBv3jyH+ysoKEBcXByWL1+OgwcP4uWXX8aLL76I5cuXm9aZN28ennjiCTz66KPYv38/1qxZg9q1a5u279q1K7Zt24YlS5bg4MGDeP311xFYlOoYichnkpKAmjWBTp2Afv3kfc2aRbPvg7/Fxnp3vUIjioGsrCwBQGRlZdm8du3aNXHw4EFx7do1l/f7+edCyJDD8e3zz73xLrQtWrRIREVFmZ6npaUJAGL27NlOt+3WrZt49tlnTc87dOggRo8ebXqekJAgBgwYYHpeUFAgqlatKubNm2dxrL179wohhNi0aZMAIH788UfTNt9++60AYDq/N998s3jiiScsynHrrbeKpk2b6n3LQgghRo0aJR544AHT82rVqomJEydqrvv999+LgIAAceTIEZeO4SpPvktE5BsrVwphMNj+XzYY5G3lSn+XsGjJzxciLk77nCnnLT5erlcYHF2/zZXqmpGiHEG2atXK4rnRaMSrr76KG2+8EZUqVULZsmXxww8/ID093eF+brzxRtNjpTno/PnzureJ/e/NK9scOXIErVu3tljf+rmW+fPno1WrVqhSpQrKli2LDz/80FT28+fP4+zZs+jcubPmtqmpqYiLi0PdunWdHoeISg5/NaUXB/aarQID5eALQHZWNac8nz27aHVeBUp5M027dnLUjL3BLQYDEB8v1ytsZcqUsXg+c+ZMvP322xg3bhw2btyI1NRU3HXXXcjNzXW4H+uOrwaDAQUFBbq3UUb+mG9jPRpIaP2nMLN8+XI888wzGDp0KH744QekpqbikUceMZXdusOuNWevE1HJVJSb0v3JWbNVr15y8EX16pbbxcX5ZlCGN5TqYKQ4RZApKSno2bMnBgwYgKZNm6JWrVo4evRooZejXr162Llzp8WyX3/91eE2KSkpaNu2LUaNGoXmzZujdu3aOHbsmOn1yMhI1KxZExs2bNDc/sYbb8Tp06fxxx9/eP4GiKjY8FdnzKLcWVZvDpFevYATJ4BNm4DPP5f3aWlySG9RfG+lOhgBik8EWbt2bSQnJ2Pbtm04dOgQHnvsMZw7d67Qy/HUU0/h448/xieffIKjR49i+vTp+O233xzmTqlduzZ+/fVXfP/99/jjjz/w0ksvYdeuXRbrTJkyBTNnzsS7776Lo0ePYs+ePXjv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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAGxCAYAAACwbLZkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABYhElEQVR4nO3deVxU5eIG8GfYFwEFZRMETMV9N3OHcMs0TS1zhWyzXFNzL/eo7nVpcbla6S1zKcFyKcsFXH6amoFLKmmCmkJqGigoCPP+/njvDAzMMDMwcIB5vp/PfHDOnOWdw8h55t2OSgghQERERKQQG6ULQERERNaNYYSIiIgUxTBCREREimIYISIiIkUxjBAREZGiGEaIiIhIUQwjREREpCiGESIiIlIUwwgREREpimGEKjWVSmXSIz4+vlTHmTdvHlQqVYm2jY+Pt0gZKrqoqCgEBwdXiOMGBwcjKirK6Lal+d0cOXIE8+bNwz///FPktbCwMISFhZm9z9JKSUmBSqXC+vXry/3YRKVhp3QBiErj6NGjOs8XLlyIuLg47N+/X2d548aNS3Wcl19+Gb179y7Rtq1bt8bRo0dLXQYy3bZt2+Du7l6mxzhy5Ajmz5+PqKgoVK9eXee1lStXlumxiaoahhGq1J544gmd57Vq1YKNjU2R5YVlZWXBxcXF5OMEBAQgICCgRGV0d3c3Wh6yrFatWil6fAZPIvOwmYaqvLCwMDRt2hQHDx5Ex44d4eLigtGjRwMAtmzZgp49e8LPzw/Ozs5o1KgRZsyYgczMTJ196GumCQ4ORt++fbF79260bt0azs7OaNiwIT7//HOd9fQ1BURFRaFatWq4dOkS+vTpg2rVqiEwMBBTpkxBdna2zvZ//vknBg8eDDc3N1SvXh3Dhw/HiRMnTKqOv3XrFt544w00btwY1apVg7e3N5588kkcOnRIZz1N9f6///1vLF26FCEhIahWrRo6dOiAn3/+uch+169fj9DQUDg6OqJRo0b44osvii2HxoABAxAUFAS1Wl3ktfbt26N169ba5ytWrEDXrl3h7e0NV1dXNGvWDB988AEePXpk9Dj6mmkuXLiA3r17w8XFBTVr1sSYMWNw7969Itvu2bMH/fv3R0BAAJycnFCvXj289tpruH37tnadefPm4a233gIAhISEFGkO1NdMc+fOHbzxxhuoXbs2HBwcULduXcyePbvI71ulUmHcuHH48ssv0ahRI7i4uKBFixbYuXOn0fdtyOHDhxEREQE3Nze4uLigY8eO2LVrl846WVlZmDp1KkJCQuDk5ARPT0+0bdsWmzZt0q5z+fJlvPDCC/D394ejoyN8fHwQERGBxMTEEpeNCGDNCFmJ1NRUjBgxAtOmTcO7774LGxuZwy9evIg+ffpg0qRJcHV1xYULF/D+++/j+PHjRZp69Dl16hSmTJmCGTNmwMfHB59++ileeukl1KtXD127di1220ePHuGZZ57BSy+9hClTpuDgwYNYuHAhPDw88M477wAAMjMzER4ejjt37uD9999HvXr1sHv3bgwZMsSk933nzh0AwNy5c+Hr64v79+9j27ZtCAsLw759+4pcMFesWIGGDRti+fLlAIC3334bffr0QXJyMjw8PADIIPLiiy+if//+WLJkCdLT0zFv3jxkZ2drz6sho0ePRv/+/bF//350795du/zChQs4fvw4PvroI+2yP/74A8OGDUNISAgcHBxw6tQpLF68GBcuXCgS+Iz566+/0K1bN9jb22PlypXw8fHBV199hXHjxhVZ948//kCHDh3w8ssvw8PDAykpKVi6dCk6d+6MM2fOwN7eHi+//DLu3LmDjz/+GLGxsfDz8wNguEbk4cOHCA8Pxx9//IH58+ejefPmOHToEKKjo5GYmFgkGOzatQsnTpzAggULUK1aNXzwwQd49tlnkZSUhLp165r13g8cOIAePXqgefPm+Oyzz+Do6IiVK1eiX79+2LRpk/azNHnyZHz55ZdYtGgRWrVqhczMTJw9exZ///23dl99+vRBXl4ePvjgA9SpUwe3b9/GkSNH9PabITKLIKpCIiMjhaurq86ybt26CQBi3759xW6rVqvFo0ePxIEDBwQAcerUKe1rc+fOFYX/uwQFBQknJydx5coV7bIHDx4IT09P8dprr2mXxcXFCQAiLi5Op5wAxNdff62zzz59+ojQ0FDt8xUrVggA4ocfftBZ77XXXhMAxLp164p9T4Xl5uaKR48eiYiICPHss89qlycnJwsAolmzZiI3N1e7/Pjx4wKA2LRpkxBCiLy8POHv7y9at24t1Gq1dr2UlBRhb28vgoKCij3+o0ePhI+Pjxg2bJjO8mnTpgkHBwdx+/Ztvdvl5eWJR48eiS+++ELY2tqKO3fuaF+LjIws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78b27dtRv359ADLcvf/++2jbti3atWuHlJQUfP/997CxsUH16tWxdu1adOrUCc2bN8e+ffuwY8cOeHl5WbSMBamEvsayCiYjIwMeHh5IT083u7MQERFJDx8+RHJyMkJCQuDk5KR0caiKKO5zZer1mzUjREREpCiGESIiIlIUwwgREREpimGEiIiIFMUwQkRkZSrBuAWqRCzxeWIYISKyEppZPbOyshQuCVUlms9T4VljzcFJz4iIrIStrS2qV6+OmzdvApBzXhiampzIGCEEsrKycPPmTVSvXl3nXjrmYhghIrIivr6+AKANJESlVb16de3nqqTMCiPR0dGIjY3FhQsX4OzsjI4dO+L9999HaGiowW3i4+MRHh5eZPn58+fRsGFD80tMREQlplKp4OfnB29v7zK98RlZB3t7+1LViGiYFUYOHDiAsWPHol27dsjNzcXs2bPRs2dPnDt3zuitmpOSknRmX6tVq1bJSkxERKVma2trkYsIkSWYFUZ2796t83zdunXw9vbGyZMn0bVr12K39fb2RvXq1c0uIBEREVVtpRpNk56eDgDw9PQ0um6rVq3g5+eHiIgIxMXFFbtudnY2MjIydB5ERERUNZU4jAghMHnyZHTu3BlNmzY1uJ6fnx/WrFmDmJgYxMbGIjQ0FBERETh48KDBbaKjo+Hh4aF9BAYGlrSYREREVMGV+K69Y8eOxa5du3D48GEEBASYtW2/fv2gUqmwfft2va9nZ2cjOztb+zwjIwOBgYG8ay8REVElUqZ37R0/fjy2b9+OuLg4s4MIADzxxBO4ePGiwdcdHR3h7u6u8yAiIqKqyawOrEIIjB8/Htu2bUN8fDxCQkJKdNCEhAT4+fmVaFsiIiKqWswKI2PHjsXGjRvx3Xffwc3NDWlpaQAADw8PODs7AwBmzpyJ69ev44svvgAALF++HMHBwWjSpAlycnKwYcMGxMTEICYmxsJvhYiIiCojs8LIqlWrAABhYWE6y9etW4eoqCgAQGpqKq5evap9LScnB1OnTsX169fh7OyMJk2aYNeuXejTp0/pSk5ERERVQok7sJYnUzvAEBERUcVRph1YiYiIiCyFYYSIiIgUxTBCREREimIYISIiIkUxjBAREZGiGEaIiIhIUQwjREREpCiGESIiIlIUwwgREREpimGEiIiIFMUwQkRERIpiGCEiIiJFMYwQERGRohhGiIiISFEMI0RERKQohhEiIiJSFMMIERERKYphhIiIiBTFMEJERESKYhghIiIiRTGMEBERkaIYRoiIiEhRDCNERESkKIYRIiIiUhTDCBERESmKYYSIiIgUxTBCREREimIYISIiIkUxjBAREZGiGEaIiIhIUQwjREREpCiGESIiIlIUwwgREREpimGEiIiIFMUwQkRERIpiGCEiIiJFMYwQERGRohhGiIiISFEMI0RERKQohhEiIiJSFMMIERERKYphhIiIiBTFMEJERESKYhghIiIiRTGMEBERkaIYRoiIiEhRDCNERESkKIYRIiIiUhTDCBERESmKYYSIiIgUxTBCREREimIYISIiIkUxjBAREZGiGEaIiIhIUQwjREREpCizwkh0dDTatWsHNzc3eHt7Y8CAAUhKSjK63YEDB9CmTRs4OTmhbt26WL16dYkLTERERFWLWWHkwIEDGDt2LH7++Wfs2bMHubm56NmzJzIzMw1uk5ycjD59+qBLly5ISEjArFmzMGHCBMTExJS68ERERFT5qYQQoqQb37p1C97e3jhw4AC6du2qd53p06dj+/btOH/+vHbZmDFjcOrUKRw9etSk42RkZMDDwwPp6elwd3cvaXGJiIioHJl6/S5Vn5H09HQAgKenp8F1jh49ip49e+os69WrF3755Rc8evRI7zbZ2dnIyMjQeRAREVHVVOIwIoTA5MmT0blzZzRt2tTgemlpafDx8dFZ5uPjg9zcXNy+fVvvNtHR0fDw8NA+AgMDS1pMIiIiquBKHEbGjRuH06dPY9OmTUbXValUOs81LUOFl2vMnDkT6enp2se1a9dKWkwiIiKq4OxKstH48eOxfft2HDx4EAEBAcWu6+vri7S0NJ1lN2/ehJ2dHby8vPRu4+joCEdHx5IUjYiIiCoZs2pGhBAYN24cYmNjsX//foSEhBjdpkOHDtizZ4/Osp9++glt27aFvb29eaUlIiKiKsesMDJ27Fhs2LABGzduhJubG9LS0pCWloYHDx5o15k5cyZGjRqlfT5mzBhcuXIFkydPxvnz5/H555/js88+w9SpUy33LoiIiKjSMiuMrFq1Cunp6QgLC4Ofn5/2sWXLFu06qampuHr1qvZ5SEgIvv/+e8THx6Nly5ZYuHAhPvroIwwaNMhy74KIiIgqrVLNM1JeOM8IERFR5VMu84wQERERlRbDCBERESmKYYSIiIgUxTBCREREimIYISIiIkUxjBAREZGiGEaIiIhIUQwjREREpCiGESIiIlIUwwgREREpimGEiIiIFMUwQkRERIpiGCEiIiJFMYwQERGRohhGiIiISFEMI0RERKQohhEiIiJSFMMIERERKYphhIiIiBTFMEJERESKYhghIiIiRTGMEBERkaIYRoiIiEhRDCNERESkKIYRIiIiUhTDCBERESmKYYSIiIgUxTBCREREimIYISIiIkUxjBAREZGiGEaIiIhIUQwjREREpCiGESIiIlIUwwgREREpimGEiIiIFMUwQkRERIpiGCEiIiJFMYwQERGRohhGiIiISFEMI0RERKQohhEiIiJSFMMIERERKYphhIiIiBTFMEJERESKYhghIiIiRTGMEBERkaIYRoiIiEhRDCNERESkKIYRIiIiUhTDCBERESmKYYSIiIgUxTBCREREimIYISIiIkUxjBAREZGiGEaIiIhIUWaHkYMHD6Jfv37w9/eHSqXCt99+W+z68fHxUKlURR4XLlwoaZmJiIioCrEzd4PMzEy0aNECL774IgYNGmTydklJSXB3d9c+r1WrlrmHJiIioirI7DDy1FNP4amnnjL7QN7e3qhevbrZ2xEREVHVVm59Rlq1agU/Pz9EREQgLi6u2HWzs7ORkZGh8yAiIqKqqczDiJ+fH9asWYOYmBjExsYiNDQUEREROHjwoMFtoqOj4eHhoX0EBgaWdTGJiIhIISohhCjxxioVtm3bhgEDBpi1Xb9+/aBSqbB9+3a9r2dnZyM7O1v7PCMjA4GBgUhPT9fpd0JEREQVV0ZGBjw8PIxevxUZ2vvEE0/g4sWLBl93dHSEu7u7zoOIiIiqJkXCSEJCAvz8/JQ4NBEREVUwZo+muX//Pi5duqR9npycjMTERHh6eqJOnTqYOXMmrl+/ji+++AIAsHz5cgQHB6NJkybIycnBhg0bEBMTg5iYGMu9CyIiIqq0zA4jv/zyC8LDw7XPJ0+eDACIjIzE+vXrkZqaiqtXr2pfz8nJwdSpU3H9+nU4OzujSZMm2LVrF/r06WOB4hMREVFlV6oOrOXF1A4wREREVHFU6A6sRERERBoMI0RERKQohhEiIiJSFMMIERERKYphhIiIiBTFMEJERESKYhghIiIiRTGMEBERkaIYRoiIiEhRDCNERESk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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "#PLOT\n",
    "acc = history.history['accuracy']\n",
    "val_acc = history.history['val_accuracy']\n",
    "loss = history.history['loss']\n",
    "val_loss = history.history['val_loss']\n",
    "\n",
    "epochs = range(len(acc))\n",
    "\n",
    "plt.plot(epochs, acc, 'bo', label='Training acc')\n",
    "plt.plot(epochs, val_acc, 'b', label='Validation acc')\n",
    "plt.title('Training and validation accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.figure()\n",
    "\n",
    "plt.plot(epochs, loss, 'bo', label='Training loss')\n",
    "plt.plot(epochs, val_loss, 'b', label='Validation loss')\n",
    "plt.title('Training and validation loss')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3317eccb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a170be15",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "1d321b4d",
   "metadata": {},
   "outputs": [],
   "source": [
    "#change working directory\n",
    "os.chdir('C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\FOUR_CARNIVORES\\\\models')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4ba3e5ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "#ENSEMBLE LEARNING"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "dfb3a6e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.preprocessing import image\n",
    "import keras.backend as K\n",
    "import numpy as np\n",
    "import cv2\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d4d2864c",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('Resnet50-swish-Adagrad.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model1 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model1.load_weights(\"Resnet50-swish-Adagrad.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e63e43d1",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('densenet-relu-Adagrad.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model2 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model2.load_weights(\"densenet-relu-Adagrad.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6bb71a73",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('vgg19-swish-Adagrad.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model3 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model3.load_weights(\"vgg19-swish-Adagrad.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "cb6b314f",
   "metadata": {},
   "outputs": [],
   "source": [
    "members=[model1,model2,model3]#actualizar!!!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "id": "aba3311a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Stacked Test Accuracy: 0.804\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import cross_val_score\n",
    "from sklearn.metrics import accuracy_score\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.ensemble import ExtraTreesClassifier\n",
    "from sklearn.ensemble import GradientBoostingClassifier\n",
    "from sklearn.ensemble import AdaBoostClassifier\n",
    "from sklearn.ensemble import BaggingClassifier\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from keras.models import load_model\n",
    "from keras.utils import to_categorical\n",
    "from numpy import dstack\n",
    "\n",
    " \n",
    "# create stacked model input dataset as outputs from the ensemble\n",
    "def stacked_dataset(members, inputX):\n",
    "\tstackX = None\n",
    "\tfor model in members:\n",
    "\t\t# make prediction\n",
    "\t\tyhat = model.predict(inputX, verbose=0)\n",
    "\t\t# stack predictions into [rows, members, probabilities]\n",
    "\t\tif stackX is None:\n",
    "\t\t\tstackX = yhat\n",
    "\t\telse:\n",
    "\t\t\tstackX = dstack((stackX, yhat))\n",
    "\t# flatten predictions to [rows, members x probabilities]\n",
    "\tstackX = stackX.reshape((stackX.shape[0], stackX.shape[1]*stackX.shape[2]))\n",
    "\treturn stackX\n",
    " \n",
    "# fit a model based on the outputs from the ensemble members\n",
    "def fit_stacked_model(members, inputX, inputy):\n",
    "\t# create dataset using ensemble\n",
    "\tstackedX = stacked_dataset(members, inputX)\n",
    "\t# fit standalone model\n",
    "\t#model = LogisticRegression()#\n",
    "\t#model = RandomForestClassifier(n_estimators=100, max_depth=None,max_features=20,min_samples_split=2, random_state=0)# n_estimators=n of trees\n",
    "\tmodel = ExtraTreesClassifier()\n",
    "\t#model = GradientBoostingClassifier()\n",
    "\t#model = AdaBoostClassifier(n_estimators=100)\n",
    "\t#model = BaggingClassifier(KNeighborsClassifier(),max_samples=0.5, max_features=0.5)\n",
    "\tmodel.fit(stackedX, inputy)\n",
    "\treturn model\n",
    " \n",
    "# make a prediction with the stacked model\n",
    "def stacked_prediction(members, model, inputX):\n",
    "\t# create dataset using ensemble\n",
    "\tstackedX = stacked_dataset(members, inputX)\n",
    "\t# make a prediction\n",
    "\tyhat = model.predict(stackedX)\n",
    "\treturn yhat\n",
    " \n",
    "\n",
    "# fit stacked model using the ensemble\n",
    "model = fit_stacked_model(members, x_train, y_train)\n",
    "# evaluate model on test set\n",
    "yhat = stacked_prediction(members, model, x_test)\n",
    "acc = accuracy_score(y_test, yhat)\n",
    "print('Stacked Test Accuracy: %.3f' % acc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "id": "1101545d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "\n",
    "filename = \"stacked_model.pickle\"\n",
    "\n",
    "# save model\n",
    "pickle.dump(model, open(filename, \"wb\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "id": "7a2912c5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "        croc       1.00      0.65      0.79        26\n",
      "       hyena       0.89      0.82      0.86        62\n",
      "     leopard       0.67      0.94      0.78        36\n",
      "        lion       0.94      0.74      0.83        39\n",
      "\n",
      "   micro avg       0.84      0.80      0.82       163\n",
      "   macro avg       0.87      0.79      0.81       163\n",
      "weighted avg       0.87      0.80      0.82       163\n",
      " samples avg       0.80      0.80      0.80       163\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\oscar\\anaconda3\\Lib\\site-packages\\sklearn\\metrics\\_classification.py:1469: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in samples with no predicted labels. Use `zero_division` parameter to control this behavior.\n",
      "  _warn_prf(average, modifier, msg_start, len(result))\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import classification_report\n",
    "vp=np.round(yhat)\n",
    "vt=y_test\n",
    "target_names = [ \"croc\",'hyena','leopard', 'lion']\n",
    "print(classification_report(vt,vp,target_names=target_names))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5347ce07",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 153,
   "id": "8c7763e0",
   "metadata": {},
   "outputs": [],
   "source": [
    "#loads image to be classified. Activate libraries\n",
    "\n",
    "from tensorflow.keras.preprocessing import image\n",
    "import keras.backend as K\n",
    "import numpy as np\n",
    "import cv2\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c41736ea",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "25c3e03f",
   "metadata": {},
   "outputs": [],
   "source": [
    "#make independent model predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "acf959d6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from keras.applications.resnet50 import preprocess_input as preprocess_resnet50\n",
    "\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for ResNet50\n",
    "    img_resnet50 = image.img_to_array(img)\n",
    "    img_resnet50 = np.expand_dims(img_resnet50, axis=0)\n",
    "    img_resnet50 = preprocess_resnet50(img_resnet50)\n",
    "\n",
    "    # Make predictions with each model\n",
    "    prediction_resnet50 = members[0].predict(img_resnet50)\n",
    "    \n",
    "    # Extract label from the image file name\n",
    "    label = file_name.split('.')[0]  # Assuming the label is the part of the file name before the first period\n",
    "    \n",
    "    # Print the final prediction and the corresponding label\n",
    "    print('Prediction:', prediction_resnet50, 'Label:', label)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "1b945126",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 85ms/step\n",
      "1/1 [==============================] - 0s 65ms/step\n",
      "1/1 [==============================] - 0s 63ms/step\n",
      "1/1 [==============================] - 0s 62ms/step\n",
      "          Label                                         Prediction\n",
      "0   FKLKN+45+1+  [[0.0011018771, 0.97842133, 0.0044411197, 0.01...\n",
      "1   FLKN+410+3+  [[0.00070779334, 0.99411833, 0.0048674904, 0.0...\n",
      "2   FLKN+49d+3+  [[0.20154403, 0.49592334, 0.067333855, 0.23519...\n",
      "3  FLKN+811+13+  [[0.086325526, 0.89340276, 0.008510469, 0.0117...\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import pandas as pd\n",
    "from keras.applications.resnet50 import preprocess_input as preprocess_resnet50\n",
    "\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select2'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Create lists to store results\n",
    "labels = []\n",
    "predictions = []\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for ResNet50\n",
    "    img_resnet50 = image.img_to_array(img)\n",
    "    img_resnet50 = np.expand_dims(img_resnet50, axis=0)\n",
    "    img_resnet50 = preprocess_resnet50(img_resnet50)\n",
    "\n",
    "    # Make predictions with each model\n",
    "    prediction_resnet50 = members[0].predict(img_resnet50)\n",
    "    \n",
    "    # Extract label from the image file name\n",
    "    label = file_name.split('.')[0]  # Assuming the label is the part of the file name before the first period\n",
    "    \n",
    "    # Append results to lists\n",
    "    labels.append(label)\n",
    "    predictions.append(prediction_resnet50)\n",
    "\n",
    "# Create a DataFrame\n",
    "results_df = pd.DataFrame({\n",
    "    'Label': labels,\n",
    "    'Prediction': predictions\n",
    "})\n",
    "\n",
    "# Print the DataFrame\n",
    "print(results_df)\n",
    "\n",
    "\n",
    "\n",
    "# Export the DataFrame to a CSV file in the folder_path\n",
    "#results_df.to_csv(os.path.join(folder_path, 'predictionsResnet.csv'), index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "bd3f6bb2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 121ms/step\n",
      "1/1 [==============================] - 0s 168ms/step\n",
      "1/1 [==============================] - 0s 139ms/step\n",
      "1/1 [==============================] - 0s 118ms/step\n",
      "          Label                                         Prediction\n",
      "0   FKLKN+45+1+  [[0.016972942, 0.960585, 0.004298272, 0.018143...\n",
      "1   FLKN+410+3+  [[0.08442394, 0.8966148, 0.003621311, 0.0153399]]\n",
      "2   FLKN+49d+3+  [[0.901319, 0.03879589, 0.021901509, 0.03798359]]\n",
      "3  FLKN+811+13+  [[0.12944134, 0.8490778, 0.015581769, 0.005899...\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import pandas as pd\n",
    "from keras.applications.densenet import preprocess_input as preprocess_densenet\n",
    "\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select2'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Create lists to store results\n",
    "labels = []\n",
    "predictions = []\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for ResNet50\n",
    "    img_dense = image.img_to_array(img)\n",
    "    img_dense = np.expand_dims(img_dense, axis=0)\n",
    "    img_dense = preprocess_densenet(img_dense)\n",
    "\n",
    "    # Make predictions with each model\n",
    "    prediction_dense = members[1].predict(img_dense)\n",
    "    \n",
    "    # Extract label from the image file name\n",
    "    label = file_name.split('.')[0]  # Assuming the label is the part of the file name before the first period\n",
    "    \n",
    "    # Append results to lists\n",
    "    labels.append(label)\n",
    "    predictions.append(prediction_dense)\n",
    "\n",
    "# Create a DataFrame\n",
    "results_df = pd.DataFrame({\n",
    "    'Label': labels,\n",
    "    'Prediction': predictions\n",
    "})\n",
    "\n",
    "# Print the DataFrame\n",
    "print(results_df)\n",
    "\n",
    "\n",
    "\n",
    "# Export the DataFrame to a CSV file in the folder_path\n",
    "#results_df.to_csv(os.path.join(folder_path, 'predictionsResnet.csv'), index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "5d48d6b5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 83ms/step\n",
      "1/1 [==============================] - 0s 81ms/step\n",
      "1/1 [==============================] - 0s 78ms/step\n",
      "1/1 [==============================] - 0s 80ms/step\n",
      "          Label                                         Prediction\n",
      "0   FKLKN+45+1+  [[4.8993643e-05, 0.97984535, 0.014743663, 0.00...\n",
      "1   FLKN+410+3+  [[0.23927452, 0.75965506, 0.0008251995, 0.0002...\n",
      "2   FLKN+49d+3+  [[0.026008101, 0.3158335, 0.060618635, 0.59753...\n",
      "3  FLKN+811+13+  [[0.023932086, 0.96286744, 0.0007293139, 0.012...\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "from keras.applications.vgg19 import preprocess_input as preprocess_vgg19\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select2'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Create lists to store results\n",
    "labels = []\n",
    "predictions = []\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for Densenet\n",
    "    img_vgg = image.img_to_array(img)\n",
    "    img_vgg = np.expand_dims(img_vgg, axis=0)\n",
    "    img_vgg = preprocess_vgg19(img_vgg)\n",
    "\n",
    "    # Make predictions with each model\n",
    "    prediction_vgg = members[2].predict(img_vgg)\n",
    "    \n",
    "    # Extract label from the image file name\n",
    "    label = file_name.split('.')[0]  # Assuming the label is the part of the file name before the first period\n",
    "    \n",
    "        # Append results to lists\n",
    "    labels.append(label)\n",
    "    predictions.append(prediction_vgg)\n",
    "\n",
    "# Create a DataFrame\n",
    "results_df = pd.DataFrame({\n",
    "    'Label': labels,\n",
    "    'Prediction': predictions\n",
    "})\n",
    "\n",
    "# Print the DataFrame\n",
    "print(results_df)\n",
    "\n",
    "\n",
    "\n",
    "# Export the DataFrame to a CSV file in the folder_path\n",
    "#results_df.to_csv(os.path.join(folder_path, 'predictionsResnet.csv'), index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3606f53f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c5ed57bf",
   "metadata": {},
   "outputs": [],
   "source": [
    "#now ensemble the three models:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "244dccae",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 61ms/step\n",
      "1/1 [==============================] - 0s 112ms/step\n",
      "1/1 [==============================] - 0s 69ms/step\n",
      "[[0.01997947 0.683821   0.26666063 0.02953891]]\n"
     ]
    }
   ],
   "source": [
    "from keras.preprocessing import image\n",
    "from keras.applications.resnet50 import preprocess_input as preprocess_resnet50\n",
    "from keras.applications.vgg19 import preprocess_input as preprocess_vgg19\n",
    "from keras.applications.densenet import preprocess_input as preprocess_densenet\n",
    "import numpy as np\n",
    "\n",
    "# Load the image\n",
    "img = image.load_img('C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select\\\\FKLKN+45+1+.bmp', target_size=(250, 200))\n",
    "\n",
    "# Preprocess the image for ResNet50\n",
    "img_resnet50 = image.img_to_array(img)\n",
    "img_resnet50 = np.expand_dims(img_resnet50, axis=0)\n",
    "img_resnet50 = preprocess_resnet50(img_resnet50)\n",
    "\n",
    "# Preprocess the image for VGG19\n",
    "img_vgg19 = image.img_to_array(img)\n",
    "img_vgg19 = np.expand_dims(img_vgg19, axis=0)\n",
    "img_vgg19 = preprocess_vgg19(img_vgg19)\n",
    "\n",
    "# Preprocess the image for DenseNet\n",
    "img_densenet = image.img_to_array(img)\n",
    "img_densenet = np.expand_dims(img_densenet, axis=0)\n",
    "img_densenet = preprocess_densenet(img_densenet)\n",
    "\n",
    "# Now, you can make predictions with each model in your ensemble\n",
    "# For example, if `members` is a list containing your three models\n",
    "prediction_resnet50 = members[0].predict(img_resnet50)\n",
    "prediction_densenet = members[1].predict(img_densenet)\n",
    "prediction_vgg19 = members[2].predict(img_vgg19)\n",
    "\n",
    "# Combine predictions according to your ensemble strategy\n",
    "# For example, you might average probabilities\n",
    "final_prediction = (prediction_resnet50 + prediction_vgg19 + prediction_densenet) / 3\n",
    "print(final_prediction)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "0ae32133",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.05771337 1.9989927  0.73263305 0.08566102]]\n"
     ]
    }
   ],
   "source": [
    "# Define the accuracies of the models\n",
    "accuracies = [80, 77, 73]\n",
    "\n",
    "# Find the maximum accuracy\n",
    "max_accuracy = max(accuracies)\n",
    "\n",
    "# Calculate the weights\n",
    "weights = [(accuracy / max_accuracy) for accuracy in accuracies]\n",
    "\n",
    "# Now you have the weights for each model\n",
    "# You can use these weights to combine the predictions\n",
    "weighted_prediction = (prediction_resnet50 * weights[0] +\n",
    "                       prediction_densenet * weights[1] +\n",
    "                       prediction_vgg19 * weights[2])\n",
    "\n",
    "print(weighted_prediction)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "822d2b11",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.02007421 0.69530183 0.2548289  0.02979514]]\n"
     ]
    }
   ],
   "source": [
    "# Define the accuracies of the models\n",
    "accuracies = [80, 77, 73]\n",
    "\n",
    "# Find the maximum accuracy\n",
    "max_accuracy = max(accuracies)\n",
    "\n",
    "# Calculate the weights\n",
    "weights = [(accuracy / max_accuracy) for accuracy in accuracies]\n",
    "\n",
    "# Now you have the weights for each model\n",
    "# You can use these weights to combine the predictions\n",
    "weighted_prediction = (prediction_resnet50 * weights[0] +\n",
    "                       prediction_densenet * weights[1] +\n",
    "                       prediction_vgg19 * weights[2])\n",
    "\n",
    "# Normalize the weighted prediction\n",
    "total_sum = weighted_prediction.sum()\n",
    "normalized_prediction = weighted_prediction / total_sum\n",
    "\n",
    "print(normalized_prediction)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "id": "0f429070",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 81ms/step\n",
      "1/1 [==============================] - 0s 123ms/step\n",
      "1/1 [==============================] - 0s 84ms/step\n",
      "[[0.01997947 0.683821   0.26666063 0.02953891]]\n",
      "1/1 [==============================] - 0s 72ms/step\n",
      "1/1 [==============================] - 0s 109ms/step\n",
      "1/1 [==============================] - 0s 88ms/step\n",
      "[[0.0168046  0.93213445 0.02103366 0.0300272 ]]\n",
      "1/1 [==============================] - 0s 74ms/step\n",
      "1/1 [==============================] - 0s 126ms/step\n",
      "1/1 [==============================] - 0s 83ms/step\n",
      "[[0.17767024 0.5407266  0.03123184 0.25037137]]\n",
      "1/1 [==============================] - 0s 58ms/step\n",
      "1/1 [==============================] - 0s 110ms/step\n",
      "1/1 [==============================] - 0s 68ms/step\n",
      "[[0.00944577 0.9015882  0.04601304 0.04295301]]\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for ResNet50\n",
    "    img_resnet50 = image.img_to_array(img)\n",
    "    img_resnet50 = np.expand_dims(img_resnet50, axis=0)\n",
    "    img_resnet50 = preprocess_resnet50(img_resnet50)\n",
    "\n",
    "# Preprocess the image for VGG19\n",
    "    img_vgg19 = image.img_to_array(img)\n",
    "    img_vgg19 = np.expand_dims(img_vgg19, axis=0)\n",
    "    img_vgg19 = preprocess_vgg19(img_vgg19)\n",
    "\n",
    "# Preprocess the image for DenseNet\n",
    "    img_densenet = image.img_to_array(img)\n",
    "    img_densenet = np.expand_dims(img_densenet, axis=0)\n",
    "    img_densenet = preprocess_densenet(img_densenet)\n",
    "\n",
    "# Now, you can make predictions with each model in your ensemble\n",
    "# For example, if `members` is a list containing your three models\n",
    "    prediction_resnet50 = members[0].predict(img_resnet50)\n",
    "    prediction_densenet = members[1].predict(img_densenet)\n",
    "    prediction_vgg19 = members[2].predict(img_vgg19)\n",
    "\n",
    "    # Combine predictions according to the ensemble strategy\n",
    "    final_prediction = (prediction_resnet50 + prediction_vgg19 + prediction_densenet) / 3\n",
    "    print(final_prediction)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "62d00b65",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 67ms/step\n",
      "1/1 [==============================] - 0s 113ms/step\n",
      "1/1 [==============================] - 0s 86ms/step\n",
      "Prediction: [[0.00604127 0.97295064 0.00782769 0.01318045]] Label: FKLKN+45+1+\n",
      "Weighted Prediction: [[0.00607366 0.97290987 0.00764494 0.01337147]] Label: FKLKN+45+1+\n",
      "1/1 [==============================] - 0s 62ms/step\n",
      "1/1 [==============================] - 0s 121ms/step\n",
      "1/1 [==============================] - 0s 87ms/step\n",
      "Prediction: [[0.10813541 0.8834627  0.00310467 0.00529719]] Label: FLKN+410+3+\n",
      "Weighted Prediction: [[0.10397901 0.88753456 0.00317524 0.00531127]] Label: FLKN+410+3+\n",
      "1/1 [==============================] - 0s 70ms/step\n",
      "1/1 [==============================] - 0s 128ms/step\n",
      "1/1 [==============================] - 0s 88ms/step\n",
      "Prediction: [[0.3762904  0.28351757 0.04995133 0.2902407 ]] Label: FLKN+49d+3+\n",
      "Weighted Prediction: [[0.380007   0.28631458 0.05003108 0.28364733]] Label: FLKN+49d+3+\n",
      "1/1 [==============================] - 0s 63ms/step\n",
      "1/1 [==============================] - 0s 148ms/step\n",
      "1/1 [==============================] - 0s 84ms/step\n",
      "Prediction: [[0.07989965 0.9017827  0.00827385 0.01004381]] Label: FLKN+811+13+\n",
      "Weighted Prediction: [[0.0810429  0.90051305 0.00841789 0.01002616]] Label: FLKN+811+13+\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "\n",
    "# Define the accuracies of the models\n",
    "accuracies = [81, 77.3, 73]\n",
    "\n",
    "# Find the maximum accuracy\n",
    "max_accuracy = max(accuracies)\n",
    "\n",
    "# Calculate the weights\n",
    "weights = [(accuracy / max_accuracy) for accuracy in accuracies]\n",
    "\n",
    "\n",
    "\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select2'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for ResNet50\n",
    "    img_resnet50 = image.img_to_array(img)\n",
    "    img_resnet50 = np.expand_dims(img_resnet50, axis=0)\n",
    "    img_resnet50 = preprocess_resnet50(img_resnet50)\n",
    "\n",
    "# Preprocess the image for VGG19\n",
    "    img_vgg19 = image.img_to_array(img)\n",
    "    img_vgg19 = np.expand_dims(img_vgg19, axis=0)\n",
    "    img_vgg19 = preprocess_vgg19(img_vgg19)\n",
    "\n",
    "# Preprocess the image for DenseNet\n",
    "    img_densenet = image.img_to_array(img)\n",
    "    img_densenet = np.expand_dims(img_densenet, axis=0)\n",
    "    img_densenet = preprocess_densenet(img_densenet)\n",
    "\n",
    "# Now, you can make predictions with each model in your ensemble\n",
    "# For example, if `members` is a list containing your three models\n",
    "    prediction_resnet50 = members[0].predict(img_resnet50)\n",
    "    prediction_densenet = members[1].predict(img_densenet)\n",
    "    prediction_vgg19 = members[2].predict(img_vgg19)\n",
    "\n",
    "    # Combine predictions according to the ensemble strategy\n",
    "    final_prediction = (prediction_resnet50 + prediction_vgg19 + prediction_densenet) / 3\n",
    "    \n",
    "    #weighted prediction\n",
    "    # Now you have the weights for each model\n",
    "    # You can use these weights to combine the predictions\n",
    "    weighted_prediction = (prediction_resnet50 * weights[0] +prediction_densenet * weights[1] +\n",
    "                       prediction_vgg19 * weights[2])\n",
    "    # Normalize the weighted prediction\n",
    "    total_sum = weighted_prediction.sum()\n",
    "    normalized_prediction = weighted_prediction / total_sum\n",
    "    \n",
    "    # Extract label from the image file name\n",
    "    label = file_name.split('.')[0]  # Assuming the label is the part of the file name before the first period\n",
    "    \n",
    "    # Print the final prediction and the corresponding label\n",
    "    print('Prediction:', final_prediction, 'Label:', label)\n",
    "    \n",
    "        # Print the final prediction and the corresponding label\n",
    "    print('Weighted Prediction:', normalized_prediction, 'Label:', label)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e46dc0ce",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fa32facd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95ce0023",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95232c87",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "39ed88eb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8661d69f",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
